#pragma once

#include "TableView.h"

#include <list>
#include <map>
#include <memory>
#include <set>
#include <string>

using std::map;
using std::list;
using std::set;
using std::wstring;

#define NODE_RADIUS 4

struct MinMaxCoord
{
    MinMaxCoord(double minLa = MAXINT,double maxLa = 0, double minLo = MAXINT,double maxLo = 0)
        :left(minLo),right(maxLo),top(minLa),bottom(maxLa){}
    double left;
    double top;
    double right;
    double bottom;


    void Update(const double latitude, const double longitude)
    {
        top = std::min<double>(top,latitude);
        bottom = std::max<double>(bottom,latitude);
        left = std::min<double>(left,longitude);
        right = std::max<double>(right,longitude);
    }
};

typedef list<Station*>								Stations;
typedef Station*                              StationIdentifier;
typedef map<StationIdentifier,list<Station*>>		StationsGraph;

class GraphCtrl :public CWnd
{
protected:
    typedef void (GraphCtrl::*method)();
    typedef std::map<UINT, method>		cmdmap_t;
public:
    GraphCtrl(void);
    virtual ~GraphCtrl(void);

    bool CreateFromStatic( UINT nStaticID, CWnd* pParent);

    void AddStation( Station* connectionStation,Station* stationToAdd);

    void AddStation( Station* connectionStation,list<Station*>& stations);

	void AddTableView(CTableView* pTableView);

    void AddLink(const wchar_t* startStation,const wchar_t* startLine,const wchar_t* endStation, const wchar_t* endLine);

    void AddLink(const int id1, const int id2);

    void Load(const wchar_t* szFilePath);

    Station* GetStation(const int id);

	const Station* GetStation(const CPoint& point);


protected:
    afx_msg void OnPaint();
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg void OnContextCmd(UINT uID);
    DECLARE_MESSAGE_MAP()
private:

    CDC& InitBackBuffer(CPaintDC &dc);
    void ReleaseBackBuffer(CPaintDC &dc);

    CRect& getClientRect(); 

    CRect ComputeRect(const Station*);

    void DrawVertex(CDC &dc ,const Station* startStation, const Station* endStation);

    void IntersectWithNode(const CRect& r1, const CRect& r2,CPoint &p1, CPoint &p2);

    void DrawInfoRect(CDC &dc);

    void DisplayContextMenu(CPoint& point);

    void ClearSelection();

    CBitmap                                 *_pOldBitmap; // Original bitmap
    CBitmap                                  _bmBack;      // Bitmap for backbuffering	
    CDC                                      _dcBack;


    StationsGraph                            _graph;
	CTableView*								 _pTableView;
    MinMaxCoord                              _minmaxCoord;  
    set<const Station*>                      _infoRect;
    map<wstring,COLORREF>                    _lineDrawSettings;
    cmdmap_t	                             _commandmap;
};

